package com.learn.egcar1.base.interceptors;

import com.learn.egcar1.base.config.InterceptorConfig;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.concurrent.ConcurrentHashMap;

public class RateLimitInterceptor implements HandlerInterceptor {
    private static final int MAX_REQUESTS_PER_MINUTE = 100;//每分钟最大请求次数
    private static final int WINDOW_SIZE_SECONDS = 60;//时间窗口

    //{“192.168.1.11”：1 “192.168.1.12”：1。。。。}  哈希map
    private final ConcurrentHashMap<String, Integer> clientCounts = new ConcurrentHashMap<>();
    //{192.168.1.11：2025-02-06 14：00：00.。。。。}
    private final ConcurrentHashMap<String, LocalDateTime> lastRestTimes = new ConcurrentHashMap<>();


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        /*
        * 1.获取客户端的ip地址 192.168.1.222;
        * 2.校验时间窗口
        *   2.1 时间为null值：记录时间和次数
        *   2.2 现在的时间大于 该ip最后一次访问时间+60秒；重置记录时间和次数
        * 3.访问次数加一
        * 4.校验次数是否超过3
        *   4.1 超过3次，抛出异常
        *   4.2 小于等于3：放行 return true;
        * */
        //获取IP地址
        String clientID = request.getRemoteAddr();
        //获取该ip地址最后的重置时间
        LocalDateTime lastRestTime = lastRestTimes.get(clientID);
        //判断
        if(lastRestTime == null || LocalDateTime.now().isAfter(lastRestTime.plusSeconds(WINDOW_SIZE_SECONDS))){
            clientCounts.put(clientID,0); //重置次数
            lastRestTimes.put(clientID,LocalDateTime.now());//重置时间
        }
        //访问次数加一
        Integer count = clientCounts.merge(clientID,1,Integer::sum);
        //判断次数
        if(count > MAX_REQUESTS_PER_MINUTE){
            throw new RuntimeException("访问次数过多，请稍后再试");
        }

        return true;
    }
}
